<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>common_grams 过滤器 | Elasticsearch: 权威指南 | Elastic</title>
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
</head>
<body>
<div class="main-container">
    <section id="content">
        
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原文地址: <a href="https://www.elastic.co/guide/cn/elasticsearch/guide/current/common-grams.html" rel="nofollow">https://www.elastic.co/guide/cn/elasticsearch/guide/current/common-grams.html</a>, 版权归 www.elastic.co 所有<br/>
                            英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/guide/current/common-grams.html" rel="nofollow">https://www.elastic.co/guide/en/elasticsearch/guide/current/common-grams.html</a>
                            </div>
                        <!-- start body -->
                  <div class="page_header">
<b>请注意:</b><br>本书基于 Elasticsearch 2.x 版本，有些内容可能已经过时。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch: 权威指南</a></span>
»
<span class="breadcrumb-link"><a href="languages.html">处理人类语言</a></span>
»
<span class="breadcrumb-link"><a href="stopwords.html">停用词: 性能与精度</a></span>
»
<span class="breadcrumb-node">common_grams 过滤器</span>
</div>
<div class="navheader">
<span class="prev">
<a href="stopwords-phrases.html">« 停用词与短语查询</a>
</span>
<span class="next">
<a href="stopwords-relavance.html">停用词与相关性 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="common-grams"></a>common_grams 过滤器<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/240_Stopwords/60_Common_grams.asciidoc">edit</a>
</h2>
</div></div></div>
<p><code class="literal">common_grams</code> 过滤器是针对短语查询能更高效的使用停用词而设计的。 它与 <code class="literal">shingles</code> 过滤器（参见 <a class="xref" href="shingles.html" title="寻找相关词">寻找相关词</a>) 类似, 为每个相邻词对生成 ，用示例解释更为容易。</p>
<p><code class="literal">common_grams</code> 过滤器根据 <code class="literal">query_mode</code> 设置的不同而生成不同输出结果：<code class="literal">false</code> （为索引使用） 或 <code class="literal">true</code> （为搜索使用），所以我们必须创建两个独立的分析器：</p>
<div class="pre_wrapper lang-json">
<pre class="programlisting prettyprint lang-json">PUT /my_index
{
  "settings": {
    "analysis": {
      "filter": {
        "index_filter": { <a id="CO175-1"></a><i class="conum" data-value="1"></i>
          "type":         "common_grams",
          "common_words": "_english_" <a id="CO175-2"></a><i class="conum" data-value="2"></i>
        },
        "search_filter": { <a id="CO175-3"></a><i class="conum" data-value="1"></i>
          "type":         "common_grams",
          "common_words": "_english_", <a id="CO175-4"></a><i class="conum" data-value="2"></i>
          "query_mode":   true
        }
      },
      "analyzer": {
        "index_grams": { <a id="CO175-5"></a><i class="conum" data-value="3"></i>
          "tokenizer":  "standard",
          "filter":   [ "lowercase", "index_filter" ]
        },
        "search_grams": { <a id="CO175-6"></a><i class="conum" data-value="3"></i>
          "tokenizer": "standard",
          "filter":  [ "lowercase", "search_filter" ]
        }
      }
    }
  }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO175-1"><i class="conum" data-value="1"></i></a><a href="#CO175-3"></a></p>
</td>
<td align="left" valign="top">
<p>首先我们基于 <code class="literal">common_grams</code> 过滤器创建两个过滤器：
<code class="literal">index_filter</code> 在索引时使用（此时 <code class="literal">query_mode</code>  的默认设置是 <code class="literal">false</code> ）， <code class="literal">search_filter</code> 在查询时使用（此时 <code class="literal">query_mode</code> 的默认设置是 <code class="literal">true</code> ）。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO175-2"><i class="conum" data-value="2"></i></a><a href="#CO175-4"></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">common_words</code> 参数可以接受与 <code class="literal">stopwords</code> 参数同样的选项（见 <a class="xref" href="using-stopwords.html#specifying-stopwords" title="指定停用词（Specifying Stopwords）">指定停用词（Specifying Stopwords）</a> ）。这个过滤器还可以接受参数 <code class="literal">common_words_path</code> ，使用存于文件里的常用词。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO175-5"><i class="conum" data-value="3"></i></a><a href="#CO175-6"></a></p>
</td>
<td align="left" valign="top">
<p>然后我们使用过滤器各创建一个索引时分析器和查询时分析器。</p>
</td>
</tr>
</table>
</div>
<p>有了自定义分析器，我们可以创建一个字段在索引时使用 <code class="literal">index_grams</code> 分析器：</p>
<div class="pre_wrapper lang-json">
<pre class="programlisting prettyprint lang-json">PUT /my_index/_mapping/my_type
{
  "properties": {
    "text": {
      "type":            "string",
      "analyzer":  "index_grams", <a id="CO176-1"></a><i class="conum" data-value="1"></i>
      "search_analyzer": "standard" <a id="CO176-2"></a><i class="conum" data-value="1"></i>
    }
  }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO176-1"><i class="conum" data-value="1"></i></a><a href="#CO176-2"></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">text</code> 字段索引时使用 <code class="literal">index_grams</code> 分析器，但是在搜索时默认使用 <code class="literal">standard</code> 分析器，稍后我们会解释其原因。</p>
</td>
</tr>
</table>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_索引时at_index_time"></a>索引时（At Index Time）<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/240_Stopwords/60_Common_grams.asciidoc">edit</a>
</h3>
</div></div></div>
<p>如果我们对短语 <code class="word">The quick and brown fox</code> 进行拆分，它生成如下词项：</p>
<div class="pre_wrapper lang-text">
<pre class="programlisting prettyprint lang-text">Pos 1: the_quick
Pos 2: quick_and
Pos 3: and_brown
Pos 4: brown_fox</pre>
</div>
<p>新的 <code class="literal">index_grams</code> 分析器生成以下词项：</p>
<div class="pre_wrapper lang-text">
<pre class="programlisting prettyprint lang-text">Pos 1: the, the_quick
Pos 2: quick, quick_and
Pos 3: and, and_brown
Pos 4: brown
Pos 5: fox</pre>
</div>
<p>所有的词项都是以 <code class="literal">unigrams</code> 形式输出的（the、quick 等等），但是如果一个词本身是常用词或者跟随着常用词，那么它同时还会在 <code class="literal">unigram</code> 同样的位置以 <code class="literal">bigram</code> 形式输出：<code class="word">the_quick</code> ， <code class="word">quick_and</code> ， <code class="word">and_brown</code> 。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_单字查询unigram_queries"></a>单字查询（Unigram Queries）<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/240_Stopwords/60_Common_grams.asciidoc">edit</a>
</h3>
</div></div></div>
<p>因为索引包含 <code class="literal">unigrams</code> ，可以使用与其他字段相同的技术进行查询，例如：</p>
<div class="pre_wrapper lang-json">
<pre class="programlisting prettyprint lang-json">GET /my_index/_search
{
  "query": {
    "match": {
      "text": {
        "query": "the quick and brown fox",
        "cutoff_frequency": 0.01
      }
    }
  }
}</pre>
</div>
<p>上面这个查询字符串是通过为文本字段配置的 <code class="literal">search_analyzer</code>  分析器 --本例中使用的是 <code class="literal">standard</code> 分析器-- 进行分析的， 它生成的词项为： <code class="word">the</code> ， <code class="word">quick</code> ， <code class="word">and</code> ， <code class="word">brown</code> ， <code class="word">fox</code> 。</p>
<p>因为 <code class="literal">text</code> 字段的索引中包含与 <code class="literal">standard</code> 分析去生成的一样的 <code class="literal">unigrams</code> ，搜索对于任何普通字段都能正常工作。</p>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_二元语法短语查询bigram_phrase_queries"></a>二元语法短语查询（Bigram Phrase Queries）<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/240_Stopwords/60_Common_grams.asciidoc">edit</a>
</h3>
</div></div></div>
<p>但是，当我们进行短语查询时，我们可以用专门的 <code class="literal">search_grams</code>  分析器让整个过程变得更高效：</p>
<div class="pre_wrapper lang-json">
<pre class="programlisting prettyprint lang-json">GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "text": {
        "query":    "The quick and brown fox",
        "analyzer": "search_grams" <a id="CO177-1"></a><i class="conum" data-value="1"></i>
      }
    }
  }
}</pre>
</div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO177-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>对于短语查询，我们重写了默认的 <code class="literal">search_analyzer</code> 分析器，而使用 <code class="literal">search_grams</code> 分析器。</p>
</td>
</tr>
</table>
</div>
<p><code class="literal">search_grams</code> 分析器会生成以下词项：</p>
<div class="pre_wrapper lang-text">
<pre class="programlisting prettyprint lang-text">Pos 1: the_quick
Pos 2: quick_and
Pos 3: and_brown
Pos 4: brown
Pos 5: fox</pre>
</div>
<p>分析器排除了所有常用词的 <code class="literal">unigrams</code>，只留下常用词的 <code class="literal">bigrams</code> 以及低频的 <code class="literal">unigrams</code>。如 <code class="word">the_quick</code> 这样的 <code class="literal">bigrams</code> 比单个词项 <code class="word">the</code> 更为少见，这样有两个好处：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
<code class="word">the_quick</code> 的位置信息要比 <code class="word">the</code> 的小得多，所以它读取磁盘更快，对系统缓存的影响也更小。
</li>
<li class="listitem">
词项 <code class="word">the_quick</code> 没有 <code class="word">the</code> 那么常见，所以它可以大量减少需要计算的文档。
</li>
</ul>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="_两词短语two_word_phrases"></a>两词短语（Two-Word Phrases）<a class="edit_me edit_me_private" rel="nofollow" title="Editing on GitHub is available to Elastic" href="https://github.com/elasticsearch-cn/elasticsearch-definitive-guide/edit/cn/240_Stopwords/60_Common_grams.asciidoc">edit</a>
</h3>
</div></div></div>
<p>我们的优化可以更进一步，因为大多数的短语查询只由两个词组成，如果其中一个恰好又是常用词，例如：</p>
<div class="pre_wrapper lang-json">
<pre class="programlisting prettyprint lang-json">GET /my_index/_search
{
  "query": {
    "match_phrase": {
      "text": {
        "query":    "The quick",
        "analyzer": "search_grams"
      }
    }
  }
}</pre>
</div>
<p>那么 <code class="literal">search_grams</code> 分析器会输出单个语汇单元：<code class="word">the_quick</code> 。这将原来昂贵的查询（查询 <code class="word">the</code> 和 <code class="word">quick</code> ）转换成了对单个词项的高效查找。</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="stopwords-phrases.html">« 停用词与短语查询</a>
</span>
<span class="next">
<a href="stopwords-relavance.html">停用词与相关性 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>